#include "startwindow.h"
#include "chatdialog.h"
#include "aboutdialog.h"

StartWindow::StartWindow(QWidget *parent)
    : QDialog(parent)
{
    chatWithLabel = new QLabel(tr("Chat With :"));
    ipAddress = new QLineEdit;
    startChatButton = new QPushButton(tr("Start Chat"));
    lowerLayout = new QHBoxLayout;
    mainLayout = new QVBoxLayout;
    lowerLayout->addWidget(ipAddress);
    lowerLayout->addWidget(startChatButton);

    this->setLayout(mainLayout);
    menuBar = new QMenuBar;
    fileMenu = new QMenu(tr("File"));
    exit = fileMenu->addAction(tr("Exit"));
    helpMenu = new QMenu(tr("Help"));
    about = helpMenu->addAction(tr("About"));
    menuBar->addMenu(fileMenu);
    menuBar->addMenu(helpMenu);
    mainLayout->setMenuBar(menuBar);
    mainLayout->addWidget(chatWithLabel);
    mainLayout->addLayout(lowerLayout);
    QObject::connect(startChatButton, SIGNAL(clicked()), this, SLOT(startChatClicked()));
    QObject::connect(&(this->recMsgThread), SIGNAL(msgAvailable(sockaddr_in,char*)), this, SLOT(newMsgArrived(sockaddr_in,char*)), Qt::BlockingQueuedConnection);
    QObject::connect(this->exit, SIGNAL(triggered()), this, SLOT(exitClicked()));
    QObject::connect(this->about, SIGNAL(triggered()), this, SLOT(aboutClicked()));
    menuBar->setVisible(TRUE);
    this->show();
    recMsgThread.start();
}

StartWindow::~StartWindow()
{
    this->recMsgThread.terminate();
    this->recMsgThread.wait();
}

void StartWindow::startChatClicked()
{
    char *ip_address;
    ip_address = strdup(this->ipAddress->text().toAscii().data());
    in_addr connect_to_ip;
    //connect_to_ip can be sirectly used for in_addr field
    //already in network byte order
    inet_aton(ip_address, &connect_to_ip);
    for(int i = 0; i < this->sessionList.length(); i++) {
        //the line below performs a byte by byte comparison of ip in list and requested ip
        //this saves the labour of overloading operators :P
        if(!strncmp((char*) &(this->sessionList[i].ip), (char*) &connect_to_ip, sizeof(connect_to_ip)))
            return;
    }
    ChatDialog *newChatDialog = new ChatDialog(this, connect_to_ip);
    newChatDialog->sessionList = &(this->sessionList);
    ip_window_list newEntry;
    newEntry.ip = connect_to_ip;
    newEntry.window = newChatDialog;
    this->sessionList.append(newEntry);
}

void StartWindow::newMsgArrived(struct sockaddr_in incoming_info, char *msg) {
    int found = 0;
    for(int i = 0; i < this->sessionList.length(); i++) {
        //make sure to check the byte order of ip before comparison
        if(strncmp((char*) &(this->sessionList[i].ip), (char*) &(incoming_info.sin_addr), sizeof(in_addr)) == 0) {
            //update chatHistory in sessionList[i].window
            msg[65535] = 0;
            fprintf(stdout, "\nmsg : %s\n ", msg);
            QString msgString = QString(msg);
            QString remoteName("\nother side : ");
            msgString = remoteName + msgString;
            msgString += "\n";
            ChatDialog *toUpdate = (ChatDialog*)(this->sessionList[i].window);
            toUpdate->chatHistory->append(msgString);
            found = 1;
        }
    }
    if(found == 0) {
        //spawn new ChatWindow
        ChatDialog *newChat = new ChatDialog(this, incoming_info.sin_addr);
        newChat->sessionList = &(this->sessionList);
        ip_window_list newEntry;
        newEntry.ip = incoming_info.sin_addr;
        newEntry.window = newChat;
        this->sessionList.append(newEntry);
        QString msgString = QString(msg);
        QString remoteName("\nother side : ");
        msgString = remoteName + msgString;
        msgString += "\n";
        newChat->chatHistory->append(msgString);
    }
}

void StartWindow::exitClicked() {
    this->recMsgThread.exit(0);
    qApp->exit(0);
}

void StartWindow::aboutClicked() {
    AboutDialog *aboutWindow = new AboutDialog;
}
